/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package simframe.util;
import java.util.Vector;
import java.util.Iterator;

/**
 *
 * @author Isaac Noble
 */
public class WeightedBucket<E> implements Iterable<E>
{
    private Vector<Double> weights = new Vector<Double>();
    private Vector<E> items = new Vector<E>();
    
    private double max_weight = 0.0;

    public class WeightedBucketIterator implements Iterator<E>
    {
        double total_weight;
        Vector<Double> draw_weights;
        Vector<Integer> draws;
        int cur_index;
        
        public WeightedBucketIterator()
        {
            total_weight = max_weight;
            draws = new Vector<Integer>();
            draw_weights = new Vector<Double>();
            for(int i = 0; i < weights.size(); i++)
            {
                draws.add(i);
                draw_weights.add(weights.get(i));
            }
            cur_index = weights.size() - 1;
        }
        
        public boolean hasNext()
        {
            if(cur_index > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        
        public E next()
        {
            double rand = Math.random() * total_weight;
            double total_so_far = 0.0;
            int index = 0;
            while(rand > (total_so_far + draw_weights.get(index)))
            {
                total_so_far += draw_weights.get(index);
                index++;
            }
            
            int draw = draws.get(index);
            total_weight -= draw_weights.get(index);
            draw_weights.set(index, draw_weights.get(cur_index));
            draws.set(index, draws.get(cur_index));
            cur_index--;
            
            return items.get(draw);
        }
        
        public void remove()
        {
            
        }
    }

    public Iterator<E> iterator()
    {
        return new WeightedBucketIterator();
    }

    public void add(E item, double weight)
    {
        items.add(item);
        weights.add(weight);
        max_weight += weight;
    }
}
